import { MultipartFile } from '@fastify/multipart';
import { Inject, Injectable, Logger, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import axios from 'axios';
import dayjs from 'dayjs';
import { isNil } from 'lodash';
import { Repository } from 'typeorm';
import { env, isDev } from '~/global/env';
import { Storage } from '~/modules/tools/storage/storage.entity';
import { AliyunOssService } from '~/shared/aliyun-oss/aliyun-oss.service';
import { FastdfsService } from '~/shared/fastdfs/fastdfs.service';

import {
  deleteFile,
  fileRename,
  getExtname,
  getFilePath,
  getFileType,
  getSize,
  saveLocalFile,
  getOssDirPath,
  getStaticFullPath,
} from '~/utils/file.util';

@Injectable()
export class UploadService {
  private readonly logger = new Logger(UploadService.name);

  constructor(
    @InjectRepository(Storage)
    private storageRepository: Repository<Storage>,
    @Inject(FastdfsService)
    private readonly fastDfs: FastdfsService,
    private aliyunOssService: AliyunOssService
  ) {}

  /**
   * 保存文件上传记录
   */
  async saveFile(file: MultipartFile & Record<string, any>): Promise<string> {
    if (isNil(file)) throw new NotFoundException('Have not any file to upload!');

    const fileName = file.filename;
    const size = getSize(file?.file?.bytesRead ?? 0);
    const extName = getExtname(fileName);
    const type = getFileType(extName);
    const name = fileRename(fileName);
    const currentDate = dayjs().format('YYYY-MM-DD');
    const path = getStaticFullPath(name, currentDate, type);

    // saveLocalFile(await file.toBuffer(), name, currentDate, type)

    if (file.toBuffer) {
      await saveLocalFile(await file.toBuffer(), name, currentDate, type);
    }
    // 判断 file.data 为Buffer类型
    if (Buffer.isBuffer(file.data)) {
      await saveLocalFile(file.data, name, currentDate, type);
    }

    await this.storageRepository.save({
      name,
      fileName,
      extName,
      path,
      type,
      size,
      userId: null,
    });

    return path;
  }

  /**
   * 保存文件上传记录
   */
  async saveFdfsFile(file: MultipartFile, userId?: number): Promise<string> {
    if (isNil(file)) throw new NotFoundException('没有文件上传!');

    const fileName = file.filename;
    const size = getSize(file.file.bytesRead);
    const extName = getExtname(fileName);
    const type = getFileType(extName);
    const name = fileRename(fileName);

    if (isDev && env('FASTDFS_UPLOAD_URL_DEV')) {
      return await this.uploadFileByDev(file);
    }

    // 上传文件到fastdfs
    const fdFile = await this.fastDfs.upload(file);

    await this.storageRepository.save({
      name,
      fileName,
      extName,
      path: fdFile.path,
      type,
      size,
      userId: userId ?? null,
      fileId: fdFile.fileId,
    });

    return fdFile.path;
  }

  /**
   * 保存文件上传记录
   */
  // async saveOssFile(file: MultipartFile & Record<string, any>): Promise<string> {
  //   if (isNil(file))
  //     throw new NotFoundException('Have not any file to upload!')

  //   const fileName = file.filename
  //   const size = getSize(file.file?.bytesRead ?? 0)
  //   const extName = getExtname(fileName)
  //   const type = getFileType(extName)
  //   const name = fileRename(fileName)
  //   const currentDate = dayjs().format('YYYY-MM-DD')
  //   const path = getFilePath(name, currentDate, type)

  //   if (file.toBuffer) {
  //     await saveLocalFile(await file.toBuffer(), name, currentDate, type)
  //   }
  //   // 判断 file.data 为Buffer类型
  //   if (Buffer.isBuffer(file.data)) {
  //     await saveLocalFile(file.data, name, currentDate, type)
  //   }

  //   try {
  // 		// 保存到阿里云OSS服务器中
  // 		const ossKey = getOssDirPath(currentDate, type, name)
  // 		const ossUrl = await this.aliyunOssService.putOssFile(ossKey, path)
  // 		this.logger.log(`save file path: ${path}: ${ossUrl}`)

  // 		await this.storageRepository.save({
  // 			name,
  // 			fileName,
  // 			extName,
  // 			path,
  // 			type,
  // 			size,
  // 			ossPath: ossKey,
  // 			ossFullPath: ossUrl
  // 		})

  // 		return ossUrl
  // 	} catch (error) {
  // 		this.logger.error(error)
  // 		throw new Error('Save file failed!')
  // 	}
  // }

  async removeFile(path: string) {
    const storage = await this.storageRepository.findOne({ where: { path } });
    if (isNil(storage)) {
      throw new NotFoundException('File not found!');
    }

    await this.storageRepository.delete(storage.id);

    // 删除文件
    await deleteFile(path);
  }

  async uploadFileByDev(file: MultipartFile): Promise<string> {
    if (isNil(file)) throw new NotFoundException('没有文件上传!');

		const buffer: any = await file.toBuffer();

    // 使用axios上传文件
    const formData = new FormData();
    const fileBlob = new Blob([buffer], { type: file.mimetype });
    formData.append('file', fileBlob, file.filename);

    const res = await axios.post(env('FASTDFS_UPLOAD_URL_DEV'), formData, {
      headers: {
        'Content-Type': 'multipart/form-data',
      },
    });

    return res?.data?.data ?? "";
  }
}
